use axum::Json;
use serde_json::Value;
use sea_orm::{ query::*, sea_query::Expr, DatabaseConnection, DbErr, DeleteResult, EntityTrait, FromQueryResult };
use crate::{ code, file::remove::remove_files_rel, query, sea_orm::connect};
use serde::{ Deserialize, Serialize };
#[derive(Debug, Deserialize, Serialize, FromQueryResult)]
pub struct Data {}
// 删除单个
pub async fn one<E:EntityTrait>(entity:E, field:&str, i32_value:Option<i32>, str_value:Option<&str>, file_names:Option<Vec<&str>>,mongo:bool) -> Result<Json<Value>, Json<Value>>{
    let conn = connect().await?;
    let table = entity.table_name();

    _ = del_file(field, i32_value, str_value, file_names, &conn, table, mongo).await?;
    
    let sql = if let Some(f) = i32_value { 
        format!("delete from {} where {}={}", table, &field, f)
    } else if let Some(f) = str_value{
        format!("delete from {} where {}=`{}`", table, &field, f)
    } else{
       "".to_owned()
    };

    let stmt = Statement::from_string(conn.get_database_backend(), sql );
    let rs= conn.execute(stmt).await;
    code::send_ok(rs)
}
// 删除多个
pub async fn many<E:EntityTrait>(entity:E, field:&str, i32_value:Option<Vec<i32>>, str_value:Option<Vec<String>>, file_names:Option<Vec<&str>>, mongo:bool) -> Result<Json<Value>, Json<Value>>{
    let conn = connect().await?;
    
    let ids = if let Some(f) = i32_value { 
        query::utils::vecstr_i32(f)?.join(",")
    } else if let Some(f) = str_value{
        f.join(",")
    } else{
        "".to_owned()
    };

    if ids.is_empty() {
        return code::err("id 不存在");
    };

    _ = del_files(field, &ids, file_names, &conn, entity.table_name(), mongo).await?;

    let result: Result<DeleteResult,DbErr> = Delete::many(entity)
    .filter(Expr::cust( format!("{} in({})", field, &ids) ))
    .exec(&conn).await;
    code::send_ok(result)
}
// 删除文件
pub async fn del_file(field:&str, i32_value:Option<i32>, str_value:Option<&str>, file_names:Option<Vec<&str>>, conn:&DatabaseConnection, table:&str, mongo:bool) -> Result<Json<Value>, Json<Value>>{
    if let Some(file_names) = file_names {
        if file_names.is_empty() { return code::ok(); }
        let names = file_names.join(",");

        let sql = if let Some(f) = i32_value { 
            format!("select {} from {} where {}={}", names, table, &field, f)
        } else if let Some(f) = str_value{
            format!("select {} from {} where {}='{}'", names, table, &field, f)
        } else{
           "".to_owned()
        };

        let stmt = Statement::from_string(conn.get_database_backend(), sql );
        let data = Data::find_by_statement(stmt).into_json().one(conn).await.unwrap_or_default();
        if let Some(f) = data {
            let mut files:Vec<String> = vec![];
            for v in &file_names {
                if let Some(path) = f[v].as_str() {
                    if mongo {
                        files.push(path.to_owned());
                    }else{
                        files.push(format!("./upload/{}", path));
                    }
                } else if let Some(k) = f[v].as_array() {
                    for r in k {
                        if let Some(path) = r.as_str() {
                            if mongo {
                                files.push(path.to_owned());
                            }else{
                                files.push(format!("./upload/{}", path));
                            }
                        }
                    }
                }
            }
            _ = remove_files_rel(files).await?;
        }
    }
    code::ok()
}
pub async fn del_files(field:&str, value:&str, file_names:Option<Vec<&str>>, conn:&DatabaseConnection, table:&str, mongo:bool) -> Result<Json<Value>, Json<Value>>{
    if let Some(file_names) = file_names {
        if file_names.is_empty() { return code::ok(); }
        let names = file_names.join(",");
        let stmt = Statement::from_string(
            conn.get_database_backend(),
            format!("select {} from {} where {} in ({})", names, table, &field, &value),
        );
        let data = Data::find_by_statement(stmt).into_json().all(conn).await.unwrap_or_default();
        if !data.is_empty() {
            let mut files:Vec<String> = vec![];
            for f in data {
                for v in &file_names {
                    if let Some(path) = f[v].as_str() {
                        if mongo {
                            files.push(path.to_owned());
                        }else{
                            files.push(format!("./upload/{}", path));
                        }
                    } else if let Some(k) = f[v].as_array() {
                        for r in k {
                            if let Some(path) = r.as_str() {
                                if mongo {
                                    files.push(path.to_owned());
                                }else{
                                    files.push(format!("./upload/{}", path));
                                }
                            }
                        }
                    }
                }
            }
            _ = remove_files_rel(files).await?;
        }
    }
    code::ok()
}
